package admindao

import (
	"go.uber.org/zap"
	"strings"
	"wzgames/internal/admin/model"
	"wzgames/internal/gdao"
	"wzgames/pkg/logger"
)

type SysDao gdao.DaoSource

const sqlCurrencyCount = "select count(*) from sys_currencies"

func (dao *SysDao) GetCurrencyTotal(name string, tp int32) (int, error) {
	var c int
	var sb strings.Builder
	sb.WriteString(sqlCurrencyCount)
	s1, args := dao.genWhere(name, tp)
	sb.WriteString(s1)
	err := dao.Get(&c, sb.String(), args...)
	return c, err
}

func (dao *SysDao) genWhere(name string, tp int32) (string, []interface{}) {
	var sb strings.Builder
	var items []string
	var args []interface{}
	if name != "" || tp > 0 {
		sb.WriteString(" where ")
		if name != "" {
			items = append(items, " `curr` like CONCAT('%',?,'%') ")
			args = append(args, name)
		}
		if tp > 0 {
			items = append(items, " `currtype`=? ")
			args = append(args, tp)
		}
	}
	if len(items) > 0 {
		sb.WriteString(strings.Join(items, " and "))
	}
	return sb.String(), args
}

const sqlGetCurrencies = "select * from sys_currencies"

func (dao *SysDao) GetCurrencyList(name string, tp int32, offset, pageSize int) ([]*model.SysCurrency, error) {
	var sb strings.Builder
	sb.WriteString(sqlGetCurrencies)
	s1, args := dao.genWhere(name, tp)
	sb.WriteString(s1)
	if pageSize == 0 {
		sb.WriteString(" order by updated desc")
	} else {
		sb.WriteString(" order by updated desc limit ?,?")
		args = append(args, offset, pageSize)
	}
	rows, err := dao.Queryx(sb.String(), args...)
	if err != nil {
		//logger.Error("err == ", zap.String("error", err.Error()))
		return nil, err
	}
	var ret []*model.SysCurrency
	for rows.Next() {
		rd := &model.SysCurrency{}
		err = rows.StructScan(rd)
		if err != nil {
			//logger.Error("err == ", zap.String("error", err.Error()))
			return nil, err
		}
		ret = append(ret, rd)
	}
	return ret, err
}

const sqlGetCurrByName = "select * from sys_currencies where `curr`=? limit 1"

func (dao *SysDao) GetCurrencyByName(name string) (*model.SysCurrency, error) {
	acc := &model.SysCurrency{}
	err := dao.Get(acc, sqlGetCurrByName, name)
	return acc, err
}

const sqlGetCurrById = "select * from sys_currencies where `currid`=? limit 1"

func (dao *SysDao) GetCurrencyById(currId int32) (*model.SysCurrency, error) {
	acc := &model.SysCurrency{}
	err := dao.Get(acc, sqlGetCurrById, currId)
	return acc, err
}

const sqlCreateSysCurr = "insert into sys_currencies(`currid`,`name`,`curr`,`currtype`,`precision`,`status`,`created`,`updated`)" +
	" values(:currid,:name,:curr,:currtype,:precision,:status,:created,:updated)"

func (dao *SysDao) CreateSysCurrency(c *model.SysCurrency) error {
	_, err := dao.NamedExec(sqlCreateSysCurr, c)
	return err
}

const sqlUpdateCurr = "update sys_currencies set `name`=:name,`curr`=:curr,`currtype`=:currtype,`precision`=:precision,`status`=:status,`updated`=:updated where `currid`=:currid"

func (dao *SysDao) UpdateSysCurrency(c *model.SysCurrency) (int64, error) {
	result, err := dao.NamedExec(sqlUpdateCurr, c)
	if err != nil {
		logger.Error("err == ", zap.String("error", err.Error()))
		return 0, err
	}
	return result.RowsAffected()
}

const sqlGetLangs = "select * from sys_langs"

func (dao *SysDao) GetSysLangs(name string) ([]*model.SysLang, error) {
	var sb strings.Builder
	sb.WriteString(sqlGetLangs)
	var args []interface{}
	if name != "" {
		sb.WriteString(" where `name` like CONCAT('%',?,'%')")
		args = append(args, name)
	}
	sb.WriteString(" order by updated desc")
	rows, err := dao.Queryx(sb.String(), args...)
	if err != nil {
		logger.Error("err == ", zap.String("error", err.Error()))
		return nil, err
	}
	var ret []*model.SysLang
	for rows.Next() {
		rd := &model.SysLang{}
		err = rows.StructScan(rd)
		if err != nil {
			logger.Error("err == ", zap.String("error", err.Error()))
			return nil, err
		}
		ret = append(ret, rd)
	}
	return ret, err
}

const sqlCreateLang = "insert into sys_langs(`name`,`desc`,`created`,`updated`) values(:name,:desc,:created,:updated) on duplicate key update `desc`=values(`desc`), updated=values(updated)"

func (dao *SysDao) CreateSysLang(c *model.SysLang) error {
	_, err := dao.NamedExec(sqlCreateLang, c)
	return err
}

const sqlGameCurrencyCount = "select count(*) from sys_games_currencies a"

func (dao *SysDao) GetGameCurrencyTotal(curr string, gameId int32) (int, error) {
	var c int
	var sb strings.Builder
	sb.WriteString(sqlGameCurrencyCount)
	s1, args := dao.genGameCurrWhere(curr, gameId)
	sb.WriteString(s1)
	err := dao.Get(&c, sb.String(), args...)
	return c, err
}

func (dao *SysDao) genGameCurrWhere(curr string, gameId int32) (string, []interface{}) {
	var sb strings.Builder
	var items []string
	var args []interface{}
	if curr != "" || gameId > 0 {
		sb.WriteString(" where ")
		if curr != "" {
			items = append(items, " a.`curr` like CONCAT('%',?,'%') ")
			args = append(args, curr)
		}
		if gameId > 0 {
			items = append(items, " a.`gameid`=? ")
			args = append(args, gameId)
		}
	}
	if len(items) > 0 {
		sb.WriteString(strings.Join(items, " and "))
	}
	return sb.String(), args
}

const sqlGetGameCurrencies = "select a.*,ifnull(b.`name`, '') as gamename from sys_games_currencies a left join sys_games b on a.gameid=b.gameid"

func (dao *SysDao) GetGameCurrencyList(curr string, gameId int32, offset, pageSize int) ([]*model.SysGameCurrency, error) {
	var sb strings.Builder
	sb.WriteString(sqlGetGameCurrencies)
	s1, args := dao.genGameCurrWhere(curr, gameId)
	sb.WriteString(s1)
	if pageSize == 0 {
		sb.WriteString(" order by a.updated desc")
	} else {
		sb.WriteString(" order by a.updated desc limit ?,?")
		args = append(args, offset, pageSize)
	}
	rows, err := dao.Queryx(sb.String(), args...)
	if err != nil {
		logger.Error("err == ", zap.String("error", err.Error()))
		return nil, err
	}
	var ret []*model.SysGameCurrency
	for rows.Next() {
		rd := &model.SysGameCurrency{}
		err = rows.StructScan(rd)
		if err != nil {
			logger.Error("err == ", zap.String("error", err.Error()))
			return nil, err
		}
		ret = append(ret, rd)
	}
	return ret, err
}

const sqlGetGameCurrById = "select * from sys_games_currencies where `gcid`=? limit 1"

func (dao *SysDao) GetGameCurrencyById(gcId int64) (*model.SysGameCurrency, error) {
	acc := &model.SysGameCurrency{}
	err := dao.Get(acc, sqlGetGameCurrById, gcId)
	return acc, err
}

const sqlCreateSysGameCurr = "insert into sys_games_currencies(`gcid`,`gameid`,`currid`,`curr`,`vtype`,`desc`,`cfg`,`status`,`created`,`updated`)" +
	" values(:gcid,:gameid,:currid,:curr,:vtype,:desc,:cfg,:status,:created,:updated)"

func (dao *SysDao) CreateSysGameCurrency(c *model.SysGameCurrency) error {
	_, err := dao.NamedExec(sqlCreateSysGameCurr, c)
	return err
}

const sqlUpdateGameCurr = "update sys_games_currencies set `gameid`=:gameid,`vtype`=:vtype,`desc`=:desc,`cfg`=:cfg,`status`=:status,`updated`=:updated where `gcid`=:gcid"

func (dao *SysDao) UpdateSysGameCurrency(c *model.SysGameCurrency) (int64, error) {
	result, err := dao.NamedExec(sqlUpdateGameCurr, c)
	if err != nil {
		logger.Error("err == ", zap.String("error", err.Error()))
		return 0, err
	}
	return result.RowsAffected()
}

const sqlCreateNodeBoot = "insert into sys_node_boot_history(`nodeid`,`dateline`) values(:nodeid,:dateline)"

func (dao *SysDao) CreateNodeBootHistory(c *model.SysNodeBootHistory) error {
	_, err := dao.NamedExec(sqlCreateNodeBoot, c)
	return err
}

// node

const sqlSysNodeCount = "select count(*) from sys_nodes"

func (dao *SysDao) GetSysNodeTotal(key, env, group string, ctId int64) (int, error) {
	var c int
	var sb strings.Builder
	sb.WriteString(sqlSysNodeCount)
	s1, args := dao.genSysNodeWhere(key, env, group, ctId)
	sb.WriteString(s1)
	err := dao.Get(&c, sb.String(), args...)
	return c, err
}

func (dao *SysDao) genSysNodeWhere(key, env, group string, ctId int64) (string, []interface{}) {
	var sb strings.Builder
	var items []string
	var args []interface{}
	if ctId > 0 {
		items = append(items, " `ctId`=? ")
		args = append(args, ctId)
	}
	if key != "" {
		items = append(items, " `nodekey` like CONCAT('%',?,'%') ")
		args = append(args, key)
	}
	if env != "" {
		items = append(items, " `env`=? ")
		args = append(args, env)
	}
	if group != "" {
		items = append(items, " `group`=? ")
		args = append(args, group)
	}
	if len(items) > 0 {
		sb.WriteString(" where ")
		sb.WriteString(strings.Join(items, " and "))
	}
	return sb.String(), args
}

const sqlGetSysNodes = "select * from sys_nodes"

func (dao *SysDao) GetSysNodeList(key, env, group string, ctId int64, offset, pageSize int) ([]*model.SysNode, error) {
	var sb strings.Builder
	sb.WriteString(sqlGetSysNodes)
	s1, args := dao.genSysNodeWhere(key, env, group, ctId)
	sb.WriteString(s1)
	if pageSize == 0 {
		sb.WriteString(" order by updated desc")
	} else {
		sb.WriteString(" order by updated desc limit ?,?")
		args = append(args, offset, pageSize)
	}
	rows, err := dao.Queryx(sb.String(), args...)
	if err != nil {
		logger.Error("err == ", zap.String("error", err.Error()))
		return nil, err
	}
	var ret []*model.SysNode
	for rows.Next() {
		rd := &model.SysNode{}
		err = rows.StructScan(rd)
		if err != nil {
			logger.Error("err == ", zap.String("error", err.Error()))
			return nil, err
		}
		ret = append(ret, rd)
	}
	return ret, err
}

const sqlGetSysNodeById = "select * from sys_nodes where `nodeid`=? limit 1"

func (dao *SysDao) GetSysNodeById(nodeId int64) (*model.SysNode, error) {
	acc := &model.SysNode{}
	err := dao.Get(acc, sqlGetSysNodeById, nodeId)
	return acc, err
}

const sqlGetSysNodeByKey = "select * from sys_nodes where `nodekey`=? limit 1"

func (dao *SysDao) GetSysNodeByKey(nodeKey string) (*model.SysNode, error) {
	acc := &model.SysNode{}
	err := dao.Get(acc, sqlGetSysNodeByKey, nodeKey)
	return acc, err
}

const sqlCreateSysNode = "insert into sys_nodes(`nodeid`,`ctid`,`nodekey`,`name`,`tz`,`env`,`group`,`status`,`remark`,`created`,`updated`)" +
	" values(:nodeid,:ctid,:nodekey,:name,:tz,:env,:group,:status,:remark,:created,:updated)"

func (dao *SysDao) CreateSysNode(c *model.SysNode) error {
	_, err := dao.NamedExec(sqlCreateSysNode, c)
	return err
}

const sqlUpdateSysNode = "update sys_nodes set `name`=:name,`nodekey`=:nodekey,`ctid`=:ctid,`tz`=:tz,`env`=:env,`group`=:group,`remark`=:remark,`status`=:status,`updated`=:updated where `nodeid`=:nodeid"

func (dao *SysDao) UpdateSysNode(c *model.SysNode) (int64, error) {
	result, err := dao.NamedExec(sqlUpdateSysNode, c)
	if err != nil {
		logger.Error("err == ", zap.String("error", err.Error()))
		return 0, err
	}
	return result.RowsAffected()
}

// container
